package com.swak.telnet.transport;

import com.swak.reactivex.transport.Codec;
import com.swak.reactivex.transport.NettyChannel;
import com.swak.reactivex.transport.NettyCodec;
import com.swak.registry.URL;
import com.swak.telnet.cmd.Command;
import com.swak.utils.StringUtils;

import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import lombok.Getter;

/**
 * 协议升级处理器: 通过 String 来升级协议
 * 
 * @author DELL
 */
public class UpgradeHandler extends ChannelDuplexHandler {

	private static final String Upgrade = "upgrade";
	private static final String Upgrade_OK = "upgrade OK!";

	@Getter
	private final URL url;
	@Getter
	private final com.swak.reactivex.transport.ChannelHandler handler;

	public UpgradeHandler(URL url, com.swak.reactivex.transport.ChannelHandler handler) {
		this.url = url;
		this.handler = handler;
	}

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		String cmd = null;
		if (msg instanceof String || msg instanceof Command) {
			cmd = msg instanceof String ? (String) msg : ((Command) msg).getCommand();
		}
		if (cmd != null && StringUtils.startsWith(cmd, Upgrade)) {

			// 升级协议
			Codec codec = new TelnetCodec(getUrl());
			NettyCodec nettyCodec = new NettyCodec(codec, getUrl(), getHandler());
			ctx.channel().pipeline().addFirst("upgrade-encoder", nettyCodec.getEncoder());
			ctx.channel().pipeline().addFirst("upgrade-decoder", nettyCodec.getDecoder());
			ctx.channel().pipeline().remove(NettyCodec.Encoder_Name);
			ctx.channel().pipeline().remove(NettyCodec.Decoder_Name);
			ctx.channel().pipeline().remove(NettyCodec.Upgrader_Name);

			// 回应已经升级
			if (Upgrade.equals(cmd)) {
				NettyChannel channel = NettyChannel.getOrAddChannel(url, ctx.channel(), handler);
				channel.send(Upgrade_OK);
			}
		} else {
			super.channelRead(ctx, msg);
		}
	}
}
